import type { StorageSetOptions } from '@/storage'
import { defineStore } from 'pinia'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import db from '@/storage'
import { appConfig } from '@/config'
import router, { routesHandler } from '@/router'
import { useRouterStore } from './router'
import { useAppSetting } from './app'
import {
  UserLoginParams,
  UserSSOLoginParams,
  userLogin,
  userSSOLogin,
  getUserMenu,
  getUserPermissions
} from '@/api/user/login'
import { authLogin, ykbAuthLogin } from '@/api/login'
import { deptTreeInfoAll } from '@/api/systemSetting/personnel'

export interface UserMenu {
  title: string
  // 唯一key，多级路由地址拼接，/开头
  path: string
  icon?: string
  link?: string
  children?: UserMenu[]
}

export interface UserInfo {
  id?: number
  username: string
  avatar?: string
  userId?: string
  [key: string]: any
}

type NavigationMenuType = {
  backEndPerms: string
  frontEndPerms: string
  icon: string
  id: number
  pid: number
  label: string
  menuType: string
  children?: Array<NavigationMenuType>
}

interface UserState {
  token: string
  userInfo: Nullable<UserInfo>
  userMenu: Nullable<UserMenu[]>
  userPermissions: Nullable<string[]>
  userPermissionMap: Map<string, boolean>
  sectionsPath: Nullable<string>
  // 41节点权限
  nodePermissionMap: Map<string, boolean>
  //菜单
  navigationMenu: Array<NavigationMenuType>
  navigationMenuMap: Map<string, boolean>
  routerList: Array<NavigationMenuType>
}

const $generatorMenu = appConfig.routesHandlerOptions.generatorMenu
const $useCustomMenu = appConfig.storeConfig.useCustomMenu

export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    token: '',
    userInfo: null,
    userMenu: null,
    userPermissions: [],
    // 用于O(1)判断权限
    userPermissionMap: new Map(),
    sectionsPath: '/',
    nodePermissionMap: new Map(),
    //菜单
    navigationMenu: [],
    navigationMenuMap: new Map(),
    //路由
    routerList: []
  }),
  getters: {
    getNavigationMenu: (state) => state.navigationMenu,
    getRouterList: (state) => {
      return db.get('routerList')
    }
  },
  actions: {
    getUserInfo() {
      return this.userInfo
    },
    async setupState() {
      this.token = db.get<string>('token') ?? this.token
      this.userInfo = db.get<UserInfo>('userInfo')
      this.sectionsPath = db.get<string>('sectionsPath') || '/'

      if (!this.token) return

      return this.reloadCurrentPage(
        Promise.all([this.setUserPermissions(), this.setUserMenu()])
      )
    },
    // 根据Permissions设置用户菜单
    setUserMenuByPermissions() {
      // 注册路由
      routesHandler.usePermissionsMenu(this.userPermissionMap)
    },
    // 设置用户菜单
    setUserMenu() {
      if ($generatorMenu || !$useCustomMenu) {
        routesHandler.setupGeneratorMenu()
        return Promise.resolve()
      }

      let http = getUserMenu
      const userMenu = db.get<UserMenu[]>('userMenu')
      if (appConfig.storeConfig.userMenuStorage && userMenu) {
        http = () => Promise.resolve({ data: userMenu })
      }

      return http().then((res) => {
        if (appConfig.storeConfig.userMenuStorage && !userMenu) {
          db.set('userMenu', res.data)
        }

        // 注册路由
        routesHandler.useRoleMenu(res.data)
        return res
      })
    },
    // 设置用户权限
    setUserPermissions() {
      let http = getUserPermissions
      const userPermissions = db.get<string[]>('userPermissions')
      if (appConfig.storeConfig.userPermissionsStorage && userPermissions) {
        http = () => Promise.resolve({ data: userPermissions })
      }

      return http().then((res) => {
        if (appConfig.storeConfig.userPermissionsStorage && !userPermissions) {
          db.set('userPermissions', res.data)
        }
        console.log('res.data', JSON.parse(JSON.stringify(res.data)))
        this.userPermissions = []
        //菜单
        this.navigationMenu = this.setNavigationMenu(
          JSON.parse(JSON.stringify(res.data))
        )
        //路由
        db.set(
          'routerList',
          this.setRouterList(JSON.parse(JSON.stringify(res.data)))
        )
        console.log(
          '路由',
          this.setRouterList(JSON.parse(JSON.stringify(res.data)))
        )
        this.getTreeRecursion(res.data)
        this.generaterPermissionMap()

        if (!$generatorMenu && !$useCustomMenu) {
          this.setUserMenuByPermissions()
        }

        return res
      })
    },
    //过滤菜单
    setNavigationMenu(arr, pid = 0) {
      if (Array.isArray(arr) && arr.length > 0) {
        arr.forEach((i) => {
          i.pid = pid
          i.name = i.frontEndPerms
          if (i.menuType === 'C' && i.visible === '0') {
            if (Array.isArray(i.children) && i.children.length > 0) {
              i.children = i.children.filter(
                (j) => j.menuType === 'C' && j.visible === '0'
              )
              this.setNavigationMenu(i.children, i.path)
            }
            this.navigationMenuMap.set(i.path, i)
          }
        })
      }
      return arr
    },
    setRouterList(arr, pid = 0) {
      const routerList = []
      if (Array.isArray(arr) && arr.length > 0) {
        arr.forEach((i) => {
          i.pid = pid
          i.name = i.frontEndPerms
          if (i.menuType === 'C') {
            if (Array.isArray(i.children) && i.children.length > 0) {
              i.children = i.children.filter((j) => j.menuType === 'C')
              this.setRouterList(i.children, i.frontEndPerms)
            }
            routerList.push(i)
          }
        })
      }
      return routerList
    },
    //获取顶级菜单
    getTopLevelMenu(path) {
      const menuMap = this.navigationMenuMap.get(path)
      if (menuMap != undefined) {
        if (menuMap.pid === 0) {
          return menuMap.children
        } else {
          return this.getTopLevelMenu(menuMap.pid)
        }
      }
      return []
    },
    //获取菜单
    getMenu(path) {
      let route = []
      try {
        route = this.getTopLevelMenu(path)
      } catch (e) {
        /* empty */
      }
      return route
    },
    // 设置节点权限
    setNodePermissionMap(perms: string[]) {
      this.nodePermissionMap = new Map()
      perms.forEach((item) => this.nodePermissionMap.set(item, true))
    },
    async loginHandler(
      data: { token: string; user: UserInfo; roleId: any },
      locationReload = false,
      isOrg = false,
      state: 1 //1正常流程 2不跳转页面
    ) {
      this.setToken(data.token, {
        expires: appConfig.serviceTokenConfig.expires
      })
      this.setUserInfo(data.user)

      await Promise.all([this.setUserPermissions(), this.setUserMenu()])

      if (locationReload) {
        if (isOrg) {
          //社会组织角色
          const url = new URL(window.location.href)
          location.href = `${url.origin}${url.pathname}#/user-menu`
          // location.href = location.origin + '/#/user-menu'
          // location.href = 'https://mzj.zgdxyyfgs.com:8000/system/#/user-menu'
          return Promise.resolve()
        } else {
          if (state === 1) {
            location.href = location.origin + location.pathname
          }
          return Promise.resolve()
        }
      } else {
        return router.push({
          name: appConfig.routeMainName
        })
      }
    },
    // 登录
    async login(params: UserLoginParams) {
      const res = await userLogin(params)
      const isOrg = this.isOrgUser(res.data.roles)
      await this.afterLoggingIn(res, isOrg)
    },
    setRoleId(roleId: string | number) {
      this.roleId = roleId
    },
    //1正常流程 2不跳转页面
    async afterLoggingIn(res, isOrg, state = 1) {

      const { access_token, user } = res.data
      this.setToken(access_token)
      let roleId = 0
      if (res.data.roles.length > 0) {
        roleId = res.data.roles[0].roleId
      }
      db.set('roleId', roleId)
      this.setRoleId(roleId)
      db.set('roleIds', res.data.roles)

      const tree = await deptTreeInfoAll()
      db.set('tree', tree.data)

      // const { permissions } = await getInfo()

      await this.loginHandler(
        {
          token: access_token,
          user: {
            ...user,
            originUsername: user.username,
            username: user.nickName
          },
          roleId: roleId
        },
        true,
        isOrg,
        state
      )
      console.log(res)
      return res
    },
    // 单点登录
    async ssoLogin(data) {
      console.log('data=>', data)
      const res = await authLogin(data.token)
      return this.afterLoggingIn(res)
    },
    // 愉快办单点登录
    async ybkSsoLogin(data) {
      console.log('data=>', data)
      ykbAuthLogin(data.authCode).then((res) => {
        console.log(res)
        return this.afterLoggingIn(res, true)
      })
      // const res = await ykbAuthLogin(data.authCode)
      // console.log(res)
      // return this.afterLoggingIn(res,true)
    },
    // 退出登录
    logout() {
      db.removeKeys('token', 'userInfo', 'userPermissions', 'userMenu')
      this.setState({
        token: '',
        userInfo: null,
        userPermissions: null,
        userPermissionMap: new Map(),
        userMenu: null,
        sectionsPath: '/'
      })

      // 处理 routerStore
      const routerStore = useRouterStore()
      routerStore.setState({
        keepAliveMap: new Map(),
        routeHistoryMap: new Map()
      })
    },
    setState(state: Partial<UserState>, dbOptions?: StorageSetOptions) {
      this.$patch(state)
      if (dbOptions) {
        db.setData(state, dbOptions)
      }
    },
    setToken(token: string, dbOptions?: StorageSetOptions) {
      this.token = token
      db.set('token', this.token, dbOptions)
    },
    setUserInfo(userInfo: UserInfo, dbOptions?: StorageSetOptions) {
      this.userInfo = userInfo
      db.set('userInfo', this.userInfo, dbOptions)
    },
    // 生成PermissionMap
    generaterPermissionMap() {
      const map = new Map<string, boolean>()
      if (this.userPermissions) {
        for (const permission of this.userPermissions) {
          map.set(permission, true)
        }
      }
      this.userPermissionMap = map
    },
    //递归
    getTreeRecursion(arr) {
      if (Array.isArray(arr) && arr.length > 0) {
        arr.forEach((i) => {
          this.userPermissions.push(i.frontEndPerms)
          if (Array.isArray(i.children) && i.children.length > 0) {
            this.getTreeRecursion(i.children)
          }
        })
      }
    },
    // 校验权限
    permissionAuth(permission: string) {
      return !!this.userPermissionMap.get(permission)
    },
    // 重载当前页
    reloadCurrentPage(promise: Promise<any>) {
      return new Promise<void>((resolve) => {
        setTimeout(() => {
          const routerStore = useRouterStore()
          routerStore.setState({
            loading: true,
            closeLoading: false
          })
          promise.then(() => {
            router
              .replace(
                location.hash ? location.hash.slice(1) : location.pathname
              )
              .then(() => {
                resolve()
                routerStore.setState({
                  loading: false,
                  closeLoading: true
                })
              })
          })
        })
      })
    },
    isOrgUser(roleList) {
      let result = roleList.some((ele, index, arr) => {
        console.log(ele.roleName)
        return ele.roleName == '社会组织工作人员'
      })
      return result
    },
    isSocialOrganization() {
      return this.isOrgUser(db.get('userInfo').roles)
    }
  }
})

export const useUserMenu = () => {
  const userStore = useUserStore()
  const { appSetting } = useAppSetting()
  const route = useRoute()

  const moduleMenu = computed((): UserMenu | null => {
    if (appSetting.value.menu.mergeModule) {
      return null
    }

    const userMenu = userStore.userMenu || []
    const routePath = route.matched[route.matched.length - 1].path

    const moduleMenu = userMenu.find((item) => routePath.includes(item.path))
    return moduleMenu || null
  })

  const userMenu = computed((): UserMenu[] => {
    const userMenu = userStore.userMenu || []

    if (appSetting.value.menu.mergeModule) {
      return userMenu
    }

    const menuItem = moduleMenu.value
    if (menuItem?.children) {
      return menuItem?.children
    }
    return menuItem ? [menuItem] : []
  })

  return {
    userMenu,
    moduleMenu
  }
}
